package ch.subgate.chessvisualizationtrainer;

import java.util.Random;

import ch.subgate.chessvisualizationtrainer.utils.CVTHelper;
import ch.subgate.chessvisualizationtrainer.utils.ChessPiece;
import ch.subgate.chessvisualizationtrainer.utils.ChessProblem;
import ch.subgate.chessvisualizationtrainer.utils.ChessProblemCollection;
import ch.subgate.chessvisualizationtrainer.utils.Constants;
import ch.subgate.chessvisualizationtrainer.utils.XmlProblemLoader;
import ch.subgate.chessvisualizationtrainer.widgets.ChessBoardView;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class QuizActivity  extends Activity implements OnClickListener {
	
	/** Determines the questions and their difficulty */
	private int mMode;
	
	/** Determines the question difficulty */
	private float mDifficulty;
	
	/** Determines whether the question is shown or the solution */
	private int mShow;
	
	/** Determines whether the first answer button is the right answer or not */
	private boolean mFirstAnswerTrue;
	
	/** The current total score */
	private float mScore;
	
	/** The number of exercises done */
	private int mExercises;
	
	/** The total training time */
	private float mTrainingTime;
	
	/** The current board type */
	private int mBoardType;
	
	/** The time stamp when a new question is created */
	private long mStartTime;
	
	/** The time stamp when a question has been solved */
	private long mSolveTime;
	
	/** The xml problem loader */
	public XmlProblemLoader mLoader;
	
	/** Is invoked when the activity is first created */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.showquiz);
		
		// Getting quiz type from intent
		Intent i = this.getIntent();
		mMode = i.getIntExtra("ch.subgate.chessvisualizationtrainer.mode", 1);
		
		// Get the score and the boardtype
		if (savedInstanceState != null) {
			mScore = savedInstanceState.getFloat("score", 0.0f);
			mExercises = savedInstanceState.getInt("exercises", 0);
			mTrainingTime = savedInstanceState.getFloat("training", 0.0f);
			mBoardType = savedInstanceState.getInt("boardType", 0);
		} else {
			mScore = i.getFloatExtra("ch.subgate.chessvisualizationtrainer.score", 0.0f);
			mExercises = i.getIntExtra("ch.subgate.chessvisualizationtrainer.exercises", 0);
			mTrainingTime = i.getFloatExtra("ch.subgate.chessvisualizationtrainer.training", 0.0f);
			mBoardType = i.getIntExtra("ch.subgate.chessvisualizationtrainer.boardtype", 0);
		}
		
		// Show a quiz as default
		mShow = Constants.SHOW_QUIZ;
		
		// Set click listeners
		Button b;
		b = (Button)findViewById(R.id.answer1);
		b.setOnClickListener(this);
		b = (Button)findViewById(R.id.answer2);
		b.setOnClickListener(this);
		
		ChessBoardView v;
		v = (ChessBoardView)findViewById(R.id.chessboardview);
		v.setOnClickListener(this);
		
		// Show the statistics
		TextView t = (TextView)findViewById(R.id.stats);
		if (mExercises < 1) {
			t.setText(getString(R.string.noproblemssolved));
		}
		else {
			t.setText(
					getString(R.string.stats) + " " +
					(int)(mScore / (float)mExercises));
		}
		
		// Begin quiz
		switch (mMode) {
			case Constants.MODE_TWOSQUARESDIAGONAL:
				mDifficulty = Constants.TWOSQUARESDIAGONAL_DIFFICULTY;
				newTwoSquaresDiagonal();
				break;
			case Constants.MODE_TWOSQUARESKNIGHTSMOVE:
				mDifficulty = Constants.TWOSQUARESKNIGHTSMOVE_DIFFICULTY;
				newTwoSquaresKnightsMove();
				break;
			case Constants.MODE_ROOKSQUEENSMATE:
				mDifficulty = Constants.ROOKSQUEENSMATE_DIFFICULTY;
				mLoader = new XmlProblemLoader(this.getResources());
				if (!mLoader.getProblemsLoaded()) {
					finish();
				}
				newLoadedPuzzle(Constants.RQMATE);
				break;
			case Constants.MODE_BISHOPSKNIGHTSMATE:
				mDifficulty = Constants.BISHOPSKNIGHTSMATE_DIFFICULTY;
				mLoader = new XmlProblemLoader(this.getResources());
				if (!mLoader.getProblemsLoaded()) {
					finish();
				}
				newLoadedPuzzle(Constants.BNMATE);
				break;
			case Constants.MODE_MATEINONE:
				mDifficulty = Constants.MATEINONE_DIFFICULTY;
				mLoader = new XmlProblemLoader(this.getResources());
				if (!mLoader.getProblemsLoaded()) {
					finish();
				}
				newLoadedPuzzle(Constants.MIONE);
				break;
			case Constants.MODE_MATEINTWO:
				mDifficulty = Constants.MATEINTWO_DIFFICULTY;
				mLoader = new XmlProblemLoader(this.getResources());
				if (!mLoader.getProblemsLoaded()) {
					finish();
				}
				newLoadedPuzzle(Constants.MITWO);
				break;
			default:
				mDifficulty = Constants.ONESQUARECOLOR_DIFFICULTY;
				newOneSquareColor();
				break;
		}
		
		// Set the default result
		setResult(RESULT_CANCELED);
	}
	
	/** This method is called upon a key press */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent e) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Intent i = new Intent(Intent.ACTION_MAIN);
			i.putExtra("ch.subgate.chessvisualizationtrainer.score", mScore);
			i.putExtra("ch.subgate.chessvisualizationtrainer.exercises", mExercises);
			i.putExtra("ch.subgate.chessvisualizationtrainer.training", mTrainingTime);
			setResult(RESULT_OK, i);
		}
		
		return super.onKeyDown(keyCode, e);
	}
	
	/** Is invoked when the activity state has to be saved */
	@Override
	public void onSaveInstanceState(Bundle outState) {
		outState.putFloat("score", mScore);
		outState.putInt("exercises", mExercises);
		outState.putFloat("training", mTrainingTime);
		outState.putInt("boardType", mBoardType);
	}
	
	/** Is invoked upon click events */
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
			case R.id.answer1:
				mSolveTime = System.currentTimeMillis();
				
				if (mFirstAnswerTrue) {
					showSolution(true, (float)(mSolveTime - mStartTime) / 1000.0f);
				}
				else {
					showSolution(false, (float)(mSolveTime - mStartTime) / 1000.0f);
				}
				break;
			case R.id.answer2:
				mSolveTime = System.currentTimeMillis();
				if (mFirstAnswerTrue) {
					showSolution(false, (float)(mSolveTime - mStartTime) / 1000.0f);
				}
				else {
					showSolution(true, (float)(mSolveTime - mStartTime) / 1000.0f);
				}
				break;
			case R.id.chessboardview:
				switch (mMode) {
					case Constants.MODE_TWOSQUARESDIAGONAL:
						newTwoSquaresDiagonal();
						break;
					case Constants.MODE_TWOSQUARESKNIGHTSMOVE:
						newTwoSquaresKnightsMove();
						break;
					case Constants.MODE_ROOKSQUEENSMATE:
						newLoadedPuzzle(Constants.RQMATE);
						break;
					case Constants.MODE_BISHOPSKNIGHTSMATE:
						newLoadedPuzzle(Constants.BNMATE);
						break;
					case Constants.MODE_MATEINONE:
						newLoadedPuzzle(Constants.MIONE);
						break;
					case Constants.MODE_MATEINTWO:
						newLoadedPuzzle(Constants.MITWO);
						break;
					default:
						newOneSquareColor();
						break;
				}
		}
	}
	
	/** Arranges the UI and hides unnecessary content */
	public void setViews() {
		if (mShow == Constants.SHOW_QUIZ) {
			Button b;
			// Make the answer buttons visible
			b = (Button)findViewById(R.id.answer1);
			b.setVisibility(View.VISIBLE);
			b = (Button)findViewById(R.id.answer2);
			b.setVisibility(View.VISIBLE);
			
			// Completely remove the solution board
			ChessBoardView v;
			v = (ChessBoardView)findViewById(R.id.chessboardview);
			v.setVisibility(View.GONE);
			TextView t;
			t = (TextView)findViewById(R.id.results);
			t.setVisibility(View.GONE);
			t = (TextView)findViewById(R.id.hint);
			t.setVisibility(View.GONE);
		}
		else {
			Button b;
			// Completely remove the answer buttons
			b = (Button)findViewById(R.id.answer1);
			b.setVisibility(View.GONE);
			b = (Button)findViewById(R.id.answer2);
			b.setVisibility(View.GONE);
			
			// Make the solution board visible
			ChessBoardView v;
			v = (ChessBoardView)findViewById(R.id.chessboardview);
			v.setVisibility(View.VISIBLE);
			TextView t;
			t = (TextView)findViewById(R.id.results);
			t.setVisibility(View.VISIBLE);
			t = (TextView)findViewById(R.id.hint);
			t.setVisibility(View.VISIBLE);
		}
	}
	
	/** Creates a new one square color puzzle */
	public void newOneSquareColor() {
		// Set the views
		mShow = Constants.SHOW_QUIZ;
		setViews();
		
		// Set the answer button texts
		Button b;
		b = (Button)findViewById(R.id.answer1);
		b.setText(getString(R.string.answerblack));
		
		b = (Button)findViewById(R.id.answer2);
		b.setText(getString(R.string.answerwhite));
		
		// Set the question text
		TextView t = (TextView)findViewById(R.id.quiz);
		t.setText(R.string.onesquarecolor_question);
		
		Random r = new Random();
		
		// Get a random square
		int x = r.nextInt(8) + 1;
		int y = r.nextInt(8) + 1;
		
		ChessBoardView v = (ChessBoardView)findViewById(R.id.chessboardview);
		v.setSquares(x, y);
		v.unsetPieces();
		
		String readableSquare = CVTHelper.getReadableSquare(x, y);
		
		if ((x + y) % 2 == 0) {
			mFirstAnswerTrue = true;
		}
		else {
			mFirstAnswerTrue = false;
		}
		
		t = (TextView)findViewById(R.id.values);
		t.setText(readableSquare);
		
		mStartTime = System.currentTimeMillis();
	}
	
	/** Creates a new two squares diagonal puzzle */
	public void newTwoSquaresDiagonal() {
		// Set the views
		mShow = Constants.SHOW_QUIZ;
		setViews();
		
		// Set the answer buttons texts
		Button b;
		b = (Button)findViewById(R.id.answer1);
		b.setText(getString(R.string.answeryes));
		
		b = (Button)findViewById(R.id.answer2);
		b.setText(getString(R.string.answerno));
		
		// Set the question text
		TextView t = (TextView)findViewById(R.id.quiz);
		t.setText(R.string.twosquarediagonal_question);
		
		Random r = new Random();
		
		// Get two random squares
		int x1 = r.nextInt(8) + 1;
		int y1 = r.nextInt(8) + 1;
		
		int x2 = r.nextInt(8) + 1;
		int y2 = r.nextInt(8) + 1;
		
		// Make sure that squares are different
		while (x1 == x2 && y1 == y2) {
			x2 = r.nextInt(8) + 1;
			y2 = r.nextInt(8) + 1;
		}
		
		// Highlight the squares on the solution board
		ChessBoardView v = (ChessBoardView)findViewById(R.id.chessboardview);
		v.setSquares(x1, y1, x2, y2);
		v.unsetPieces();
		
		// Get readable square coordinate strings
		String readableSquare1 = CVTHelper.getReadableSquare(x1, y1);
		String readableSquare2 = CVTHelper.getReadableSquare(x2, y2);
		
		if (CVTHelper.isDiagonal(x1, y1, x2, y2)) {
			mFirstAnswerTrue = true;
		}
		else {
			mFirstAnswerTrue = false;
		}
		
		t = (TextView)findViewById(R.id.values);
		t.setText(readableSquare1 + " " + readableSquare2);
		
		mStartTime = System.currentTimeMillis();
	}
	
	/** Creates a new two squares knights move puzzle */
	public void newTwoSquaresKnightsMove() {
		// Set the views
		mShow = Constants.SHOW_QUIZ;
		setViews();
		
		// Set the answer buttons texts
		Button b;
		b = (Button)findViewById(R.id.answer1);
		b.setText(getString(R.string.answeryes));
		
		b = (Button)findViewById(R.id.answer2);
		b.setText(getString(R.string.answerno));
		
		// Set the question text
		TextView t = (TextView)findViewById(R.id.quiz);
		t.setText(R.string.twosquaresknightmove_question);
		
		Random r = new Random();
		
		// Get two random squares
		int x1 = r.nextInt(8) + 1;
		int y1 = r.nextInt(8) + 1;
		
		int dx = r.nextInt(3) + 1;
		int dy = r.nextInt(3) + 1;
		
		boolean var;
		int x2;
		int y2;
		
		// Algorithm to get a target square that only slightly varies from N move
		if (x1 + dx > 8) {
			x2 = x1 - dx;
		}
		else if (x1 - dx < 1) {
			x2 = x1 + dx;
		}
		else {
			var = r.nextBoolean();
			x2 = var ? x1 + dx : x1 - dx;
		}
		if (y1 + dy > 8) {
			y2 = y1 - dy;
		}
		else if (y1 - dy < 1) {
			y2 = y1 + dy;
		}
		else {
			var = r.nextBoolean();
			y2 = var ? y1 + dy : y1 - dy;
		}
		
		// Highlight the squares on the solution board
		ChessBoardView v = (ChessBoardView)findViewById(R.id.chessboardview);
		v.setSquares(x1, y1, x2, y2);
		v.unsetPieces();
		
		// Get readable square coordinate strings
		String readableSquare1 = CVTHelper.getReadableSquare(x1, y1);
		String readableSquare2 = CVTHelper.getReadableSquare(x2, y2);
		
		if (CVTHelper.isKnightMove(x1, y1, x2, y2)) {
			mFirstAnswerTrue = true;
		}
		else {
			mFirstAnswerTrue = false;
		}
		
		t = (TextView)findViewById(R.id.values);
		t.setText(readableSquare1 + " " + readableSquare2);
		
		mStartTime = System.currentTimeMillis();
	}
	
	/** Gets a new Rooks & Queens mate puzzle */
	public void newLoadedPuzzle(String type) {
		// Set the views
		mShow = Constants.SHOW_QUIZ;
		setViews();
		
		ChessProblemCollection collection = mLoader.getCollection(type);
		
		if (collection == null) {
			finish();
			return;
		}
		
		Button b = (Button)findViewById(R.id.answer1);
		b.setText(collection.getAnswerA());
		b = (Button)findViewById(R.id.answer2);
		b.setText(collection.getAnswerB());
		
		TextView t = (TextView)findViewById(R.id.quiz);
		t.setText(collection.getQuestion());
		
		ChessProblem problem = collection.getRandomProblem();
		
		if (problem == null) {
			finish();
			return;
		}
		
		t = (TextView)findViewById(R.id.values);
		String val = "";
		for (ChessPiece piece : problem.getPieces()) {
			val = val.concat(piece.getReadable() + " ");
		}
		val.trim();
		t.setText(val);
		
		ChessBoardView v = (ChessBoardView)findViewById(R.id.chessboardview);
		v.setPieces(problem.getPieces());
		v.unsetSquares();
		
		if (problem.getSolution().equalsIgnoreCase(collection.getAnswerA())) {
			mFirstAnswerTrue = true;
		}
		else {
			mFirstAnswerTrue = false;
		}
		
		mStartTime = System.currentTimeMillis();
	}
	
	/** Brings up the solution */
	public void showSolution(boolean solved, float dt) {
		// Set the views
		mShow = Constants.SHOW_SOLUTION;
		setViews();
		
		// Increment the number of exercises done
		mExercises++;
		
		// Adjust total training time
		mTrainingTime += dt;
		
		float ds;
		TextView t = (TextView)findViewById(R.id.quiz);
		if (solved) {
			t.setText(R.string.good_answer);
			ds = CVTHelper.getDeltaScore(mDifficulty, dt);
		}
		else {
			t.setText(R.string.bad_answer);
			ds = -10.0f;
		}
		
		mScore += ds;
		
		// Show the statistics
		t = (TextView)findViewById(R.id.stats);
		if (mExercises < 1) {
			t.setText(getString(R.string.noproblemssolved));
		}
		else {
			t.setText(
					getString(R.string.stats) + " " +
					(int)(mScore / (float)mExercises));
		}
		t = (TextView)findViewById(R.id.results);
		t.setText(
				getString(R.string.solution1) + " " +
				(int)dt + " " +
				getString(R.string.solution2) + " " +
				(int)ds + " " +
				getString(R.string.solution3));
	}
}
